<?php

namespace ff\view;

class template
{

    public $subtemplates = array();
    public $replacecode = array('search' => array(), 'replace' => array());
    public $tplfile = '';
    public $cachefile = '';
    public $config = '';

    public function __construct($config = array())
    {
        $this->config = $config;
    }

    public function cache($tplfile, $cachefile = '')
    {

        if (is_file(SYSTEM_ROOT_PATH . $tplfile)) {
            $this->tplfile = SYSTEM_ROOT_PATH . $tplfile;
        } else {
            $this->tplfile = SYSTEM_ROOT_PATH . '/views/' . $tplfile . '.htm';
        }
        
        if (!file_exists($this->tplfile)) {
            throw new \Exception(" Unable to find Template File : '{$tplfile}' ");
        }

        if (!$cachefile) {
            $this->cachefile = SYSTEM_ROOT_PATH . '/runtime/template/' . $templatedir_cache . md5($tplfile) . '.php';
        }

        if (file_exists($this->tplfile)) {
            if ((@filemtime($this->tplfile) > @filemtime($this->cachefile))) {
                $this->compile($tplfile, $cachefile);
            }
        } else {
            $this->compile($tplfile, $cachefile);
        }

        return $this->cachefile;
    }

    public function compile($tplfile, $cachefile = '')
    {

        if ($fp = @fopen($this->tplfile, 'r')) {
            $template = @fread($fp, filesize($this->tplfile));
            fclose($fp);
        } else {
            $this->error('template_notfound', $tplfile);
        }

        $var_regexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\-\>)?[a-zA-Z0-9_\x7f-\xff]*)(\[[a-zA-Z0-9_\-\.\"\'\[\]\$\x7f-\xff]+\])*)";
        $const_regexp = "([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)";

        $this->subtemplates = array();
        for ($i = 1; $i <= 3; $i++) {
            if (preg_match('/{subtemplate/is', $template)) {
                $template = preg_replace_callback("/[\n\r\t]*(\<\!\-\-)?\{subtemplate\s+([a-z0-9_:\/]+)\}(\-\-\>)?[\n\r\t]*/is", function ($r) {return $this->loadsubtemplate($r[2]);}, $template);
            }
        }

        $template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);
        $template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);
        $template = preg_replace_callback("/[\n\r\t]*\{eval\}\s*(\<\!\-\-)*(.+?)(\-\-\>)*\s*\{\/eval\}[\n\r\t]*/is", function ($r) {return $this->evaltags($r[2]);}, $template);
        $template = preg_replace_callback("/[\n\r\t]*\{eval\s+(.+?)\s*\}[\n\r\t]*/is", function ($r) {return $this->evaltags($r[1]);}, $template);
        $template = str_replace("{LF}", "<?=\"\\n\"?>", $template);
        $template = preg_replace("/\{(\\\$[a-zA-Z0-9_\-\>\[\]\'\"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);

        $template = preg_replace_callback("/$var_regexp/s", function ($r) {return template::addquote('<?=' . $r[1] . '?>');}, $template);
        $template = preg_replace_callback("/\<\?\=\<\?\=$var_regexp\?\>\?\>/s", function ($r) {return $this->addquote('<?=' . $r[1] . '?>');}, $template);

        if ($this->subtemplates) {
            foreach ($this->subtemplates as $subtplfile) {
                $subtplchecktemplate .= "\n\$TP->subtplcheckrefresh('{$subtplfile}','{$tplfile}');";
            }

        }

        $template = "<? if(!defined('SYSTEM_IN')) exit('Access Denied'); $subtplchecktemplate ?>\n$template";

        $template = preg_replace_callback("/[\n\r\t]*\{template\s+([a-z0-9_:\/]+)\}[\n\r\t]*/is", function ($r) {return $this->stripvtags('<? include $TP->cache(\'' . $r[1] . '\'); ?>');}, $template);
        $template = preg_replace_callback("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/is", function ($r) {return $this->stripvtags('<? include $TP->cache(\'' . $r[1] . '\'); ?>');}, $template);
        $template = preg_replace_callback("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/is", function ($r) {return $this->stripvtags('<? echo ' . $this->getphpfilter($r[1]) . ' ?>');}, $template);

        $template = preg_replace_callback("/([\n\r\t]*)\{if\s+(.+?)\}([\n\r\t]*)/is", function ($r) {return $this->stripvtags($r[1] . '<? if(' . $r[2] . ') { ?>' . $r[3]);}, $template);
        $template = preg_replace_callback("/([\n\r\t]*)\{elseif\s+(.+?)\}([\n\r\t]*)/is", function ($r) {return $this->stripvtags($r[1] . '<? } elseif(' . $r[2] . ') { ?>' . $r[3]);}, $template);

        $template = preg_replace("/\{else\}/i", "<? } else { ?>", $template);
        $template = preg_replace("/\{\/if\}/i", "<? } ?>", $template);

        $template = preg_replace_callback("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r\t]*/is", function ($r) {return $this->stripvtags('<? if(is_array(' . $r[1] . ')) foreach(' . $r[1] . ' as ' . $r[2] . ') { ?>');}, $template);
        $template = preg_replace_callback("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*/is", function ($r) {return $this->stripvtags('<? if(is_array(' . $r[1] . ')) foreach(' . $r[1] . ' as ' . $r[2] . ' => ' . $r[3] . ') { ?>');}, $template);

        $template = preg_replace("/\{\/loop\}/i", "<? } ?>", $template);

        $template = preg_replace("/\{$const_regexp\}/s", "<?=\\1?>", $template);
        if (!empty($this->replacecode)) {
            $template = str_replace($this->replacecode['search'], $this->replacecode['replace'], $template);
        }
        $template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);

        $template = preg_replace_callback("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/", function ($r) {return $this->transamp($r[1]);}, $template);
        $template = preg_replace_callback("/\<script[^\>]*?src=\"(.+?)\"(.*?)\>\s*\<\/script\>/is", function ($r) {return $this->stripscriptamp($r[1], $r[2]);}, $template);

        $template = preg_replace("/\<\?(\s{1})/is", "<?php\\1", $template);
        $template = preg_replace("/\<\?\=(.+?)\?\>/is", "<?php echo \\1;?>", $template);

        if (!@$fp = fopen($this->cachefile, 'w')) {
            $this->error('directory_notfound', dirname($this->cachefile));
        }

        flock($fp, 2);
        fwrite($fp, $template);
        fclose($fp);

    }

    public function loadsubtemplate($file)
    {

        if (defined('IS_MOBILE') && IS_MOBILE) {
            $templatedir = 'template_mobile';
            $templatedir_cache = 'mobile_';
        } else {
            $templatedir = 'template';
            $templatedir_cache = '';
        }

        $tplfile = SYSTEM_ROOT_PATH . 'source/' . $templatedir . '/' . $file . '.htm';
        if (!file_exists($this->tplfile)) {
            $tplfile = SYSTEM_ROOT_PATH . 'source/template/' . $file . '.htm';
        }

        $cachefile = SYSTEM_ROOT_PATH . 'data/template/' . $templatedir_cache . md5($file) . '.php';

        if (($content = @implode('', file($tplfile)))) {
            $this->subtemplates[] = $file;
            return $content;
        } else {
            return '<!-- ' . $file . ' -->';
        }
    }

    public function subtplcheckrefresh($subtplfile, $tplfile)
    {

        if (defined('IS_MOBILE') && IS_MOBILE) {
            $templatedir = 'template_mobile';
            $templatedir_cache = 'mobile_';
        } else {
            $templatedir = 'template';
            $templatedir_cache = '';
        }

        $subtplfile = SYSTEM_ROOT_PATH . 'source/' . $templatedir . '/' . $subtplfile . '.htm';
        if (!file_exists($subtplfile)) {
            $subtplfile = SYSTEM_ROOT_PATH . 'source/template/' . $subtplfile . '.htm';
        }

        $cachefile = SYSTEM_ROOT_PATH . 'data/template/' . $templatedir_cache . md5($tplfile) . '.php';

        if (file_exists($subtplfile)) {

            if ((@filemtime($subtplfile) > @filemtime($cachefile))) {

                $this->compile($tplfile, $cachefile);
            }
        }

    }

    public function getphptemplate($content)
    {
        $pos = strpos($content, "\n");
        return $pos !== false ? substr($content, $pos + 1) : $content;
    }

    public function getphpfilter($content)
    {

        if (preg_match('/[^;]\s*$/is', $content)) {
            $content = trim($content) . ';';
        }
        return $content;
    }

    public function evaltags($php)
    {
        $php = str_replace('\"', '"', $php);
        $i = count($this->replacecode['search']);
        $this->replacecode['search'][$i] = $search = "<!--EVAL_TAG_$i-->";
        $this->replacecode['replace'][$i] = "<? $php?>";
        return $search;
    }

    public function transamp($str)
    {
        $str = str_replace('&', '&amp;', $str);
        $str = str_replace('&amp;amp;', '&amp;', $str);
        $str = str_replace('\"', '"', $str);
        return $str;
    }

    public function addquote($var)
    {
        return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
    }

    public function stripvtags($expr, $statement = '')
    {
        $expr = str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\\1", $expr));
        $statement = str_replace("\\\"", "\"", $statement);
        return $expr . $statement;
    }

    public function stripscriptamp($s, $extra)
    {
        $extra = str_replace('\\"', '"', $extra);
        $s = str_replace('&amp;', '&', $s);
        return "<script src=\"$s\" type=\"text/javascript\"$extra></script>";
    }

    public function error($message, $tplname)
    {
        core_error::template_error($message, $tplname);
    }
    public function fileext($filename)
    {
        return addslashes(strtolower(substr(strrchr($filename, '.'), 1, 10)));
    }

}
